﻿using GalaSoft.MvvmLight.Helpers;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using Windows.ApplicationModel;
using Windows.Storage;

namespace WindowsStoreApps.Model
{
    public class MainPageDataService : IDataService<MainPageDataItem, Exception>
    {
        public void GetData(Action<MainPageDataItem, Exception> callback)
        {
            // Use this to connect to the actual data service
            var item = new MainPageDataItem("Network Practice",
                "Some network tech points in windows store app.\\n You can try to use those function in owner project.",
                "WindowsStoreApps.Views.NetworkView");

            callback(item, null);
        }

        public Task GetDataAsync(CancellationToken token, 
            Action<DateItemAndExcepton<MainPageDataItem, Exception>> callback, 
            Action completed = null)
        {
            var weakCallback = new WeakAction<DateItemAndExcepton<MainPageDataItem, Exception>>(callback);
            var weakCompleted = new WeakAction(completed);

            Task task = Task.Run(
                async () =>
                {
                    await loadDataAsync(token, weakCallback, weakCompleted);
                }, token);

            return task;
        }

        private async Task loadDataAsync(CancellationToken token,
            WeakAction<DateItemAndExcepton<MainPageDataItem, Exception>> callback,
            WeakAction completed = null)
        {
            try
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Async = true;

                using (var stream = await Package.Current.InstalledLocation.OpenStreamForReadAsync(@"Data\Items.xml"))
                {
                    using (XmlReader reader = XmlReader.Create(stream, settings))
                    {
                        while (await reader.ReadAsync())
                        {
                            if (token.IsCancellationRequested)
                            {
                                Debug.WriteLine("##==> loading data has been cancelled");
                                token.ThrowIfCancellationRequested();
                            }

                            if (reader.NodeType == XmlNodeType.Element &&
                                reader.Name == "it" &&
                                reader.HasAttributes)
                            {
                                var title = reader.GetAttribute("title");
                                var description = reader.GetAttribute("description");
                                var view = reader.GetAttribute("view");
                                var action = reader.GetAttribute("action");

                                MainPageDataItem item = new MainPageDataItem(title, description, view) { Action = action };
                                doCallback(callback, new DateItemAndExcepton<MainPageDataItem, Exception>() { Item = item });

                                await Task.Delay(10);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                doCallback(callback, new DateItemAndExcepton<MainPageDataItem, Exception>() { Exp = ex });
            }
            finally
            {
                doCompleted(completed);
            }
        }

        private void doCallback(WeakAction<DateItemAndExcepton<MainPageDataItem, Exception>> callback,
            DateItemAndExcepton<MainPageDataItem, Exception> result)
        {
            if (callback != null)
            {
                callback.Execute(result);
            }
        }

        private void doCompleted(WeakAction completed)
        {
            if (completed != null)
            {
                completed.Execute();
            }
        }
    }
}